class_name SkillAgent
extends Node2D

#region 属性
@export var entity:Entity
## 当前已添加的Skill
var added_skill_dict:Dictionary[String,Skill] = {}
## 当前正在释放的技能
var running_skill_dict:Dictionary = {}
var skill_history:Array[String] = []
var skill_history_max_count:int = 20
var connect_obj_dict:Dictionary = {}
#endregion
#region 字段
var is_releasing_skill:bool:
	get:
		return running_skill_dict.size() > 0
#endregion
#region 信号
signal skill_added(skill_id:String)
signal skill_removed(skill_id:String)
#endregion

#region 基类方法
#endregion
#region 公共方法
## 添加技能
func add_skill(skill_id:String,args:Dictionary = {}) -> Skill:
	var skill_info:SkillInfo = GameSkillSystem.get_skill_info_by_id(skill_id)
	if not skill_info or added_skill_dict.has(skill_id):
		return
	var skill:Skill = skill_info.skill_scene.instantiate()
	add_child(skill)
	args[SkillBlackboardKey.Agent] = self
	args[SkillBlackboardKey.SkillInfo] = skill_info
	skill.init(args)
	added_skill_dict.set(skill_id,skill)
	skill_added.emit(skill_id)
	return skill
## 添加多个技能
func add_skills(skill_ids:Array[String]) -> Array[Skill]:
	var skills:Array[Skill] = []
	for skill_id in skill_ids:
		skills.append(add_skill(skill_id))
	return skills
## 删除技能
func remove_skill(skill_id:String):
	var skill = added_skill_dict.get(skill_id,null)
	if not skill:
		return
	skill.destroy()
	added_skill_dict.erase(skill_id)
	skill_removed.emit(skill_id)
## 删除所有技能
func remove_all_skills():
	for skill_id in added_skill_dict.keys():
		remove_skill(skill_id)
## 释放技能
func release_skill(skill_id:String,args:Dictionary = {},add_history:bool = true) -> GameEnum.SkillReleaseStatus:
	var skill:Skill = get_skill_by_skill_id(skill_id)
	if not skill:
		return GameEnum.SkillReleaseStatus.NoAdded
	# 先根据条件判断下能否释放
	if not check_can_release_skill():
		return GameEnum.SkillReleaseStatus.AgentCantRelease
	var status = skill.check_can_release()
	if status != GameEnum.SkillReleaseStatus.Success:
		return status
	# 先根据优先级处理下当前正在释放的技能
	_filter_by_priority(skill)
	running_skill_dict[skill_id] = skill
	if args.has(SkillBlackboardKey.InitPos):
		skill.global_position = args.get(SkillBlackboardKey.InitPos)
	if args.has(SkillBlackboardKey.InitDir):
		skill.look_at(skill.global_position + args.get(SkillBlackboardKey.InitDir).normalized())
	if args.has(SkillBlackboardKey.InitMarkPath):
		var state_action = args.get("StateAction")
		if state_action:
			var mark:Marker2D = state_action.get_node(args.get(SkillBlackboardKey.InitMarkPath))
			if mark:
				skill.global_position = mark.global_position
				skill.global_rotation = mark.global_rotation
	skill.release(args)
	if add_history:
		skill_history.push_back(skill_id)
		while skill_history.size() > skill_history_max_count:
			skill_history.pop_front()
	return GameEnum.SkillReleaseStatus.Success
## 取消某个技能的释放
func cancel_skill(skill_id:String):
	var skill:Skill = get_skill_by_skill_id(skill_id)
	if not skill:
		return
	interrupt_skill(skill_id)
## 打断技能
func interrupt_skill(skill_id:String):
	var skill:Skill = get_skill_by_skill_id(skill_id)
	if not skill:
		return
	skill.interrupt()
	running_skill_dict.erase(skill_id)
## 打断全部技能
func interrupt_all_skill():
	for skill_id in added_skill_dict.keys():
		interrupt_skill(skill_id)
## 判断能否释放技能
func check_can_release_skill():
	return true
## 判断能否是否指定SkillId的技能
func check_can_release_skill_by_id(skill_id:String) -> bool:
	if not check_can_release_skill():
		return false
	var skill = get_skill_by_skill_id(skill_id)
	if not skill:
		return false
	return skill.check_can_release() == GameEnum.SkillReleaseStatus.Success
## 重置某技能的冷却时间
func reset_skill_cooling_time(skill_id:String):
	var skill:Skill = get_skill_by_skill_id(skill_id)
	if not skill:
		return
	skill.reset_cool()
## 重置所有技能的冷却时间
func reset_all_skill_cooling_time():
	for skill_id in added_skill_dict.keys():
		reset_skill_cooling_time(skill_id)
## 获取当前正在释放的技能Skill_id
func get_running_skill_ids() -> Array[String]:
	return running_skill_dict.keys()
## 获得指定Skill_id的技能
func get_skill_by_skill_id(skill_id:String) -> Skill:
	return added_skill_dict.get(skill_id,null)
#endregion
#region 私有方法
func _filter_by_priority(skill:Skill):
	match skill.priority_conflict_resolution:
		GameEnum.SkillPriorityConflictResolution.Ignore:
			return
		GameEnum.SkillPriorityConflictResolution.InterruptLowerPriority:
			var id_reverse = running_skill_dict.keys()
			id_reverse.reverse()
			for id in id_reverse:
				var cur_skill:Skill = running_skill_dict[id]
				if cur_skill.priority < skill.priority:
					interrupt_skill(id)
			return
		GameEnum.SkillPriorityConflictResolution.Solo:
			var id_reverse = running_skill_dict.keys()
			id_reverse.reverse()
			for id in id_reverse:
				var cur_skill:Skill = running_skill_dict[id]
				interrupt_skill(id)
			return
		_:
			return
#endregion
#region 生命周期函数
func _notification(what: int) -> void:
	if what == NOTIFICATION_PREDELETE:
		interrupt_all_skill()
#endregion
